#pragma once
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <string>
#include "log.hpp"
#include "threadpool.hpp"
#include "Task.hpp"
#include "daemon.hpp"
#define SIZE 1024
extern Log lg;
const int defaultfd = -1;
const std::string defaultip = "127.0.0.1";
const uint16_t defaultport = 8808;
const int backlg = 5;

enum
{
    LISTEN_ERR = 1,
    BIND_ERR,
    SOCK_ERR

};
class TcpServer
{
private:
    int listen_fd;         // 监听套接字
    std::string serverip_; // 服务端ip
    uint16_t server_port;  // 服务端端口

public:
    TcpServer(const uint16_t &port = defaultport, const std::string &ip = defaultip)
        : listen_fd(-1), serverip_(ip), server_port(port)
    {
    }
    void Init() // 服务器初始化
    {
        // 1.套接字创建
        listen_fd = socket(AF_INET, SOCK_STREAM, 0);
        if (listen_fd < 0)
        {
            lg(FATAL, "Create socket fail!! errno is: %d, errmessage is: %s", errno, strerror(errno));
            exit(SOCK_ERR);
        }
        lg(INFO, "Listen sucess!! listenfd is %d", listen_fd);
        int opt=1;
        setsockopt(listen_fd,SOL_SOCKET,SO_REUSEADDR|SO_REUSEPORT,&opt,sizeof(opt));//防止偶发性服务器无法进行立即重启
        // 2.准备数据
        struct sockaddr_in local;
        memset(&local, 0, sizeof(local)); // 初始化结构体
        local.sin_family = AF_INET;
        local.sin_port = htons(server_port);                    // 主机转网络字节序
        inet_pton(AF_INET, serverip_.c_str(), &local.sin_addr); // 字符串转网络地址
        // 3.bind
        if (bind(listen_fd, (sockaddr *)&local, sizeof(local)) < 0)
        {
            lg(FATAL, "Bind socket fail!! errno is:%d, errmessage is: %s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(INFO, "Bind sucess!! ");
        // 4. 监听，让服务器保持一种一直在等待被连接的状态
        if (listen(listen_fd, backlg) < 0)
        {
            lg(FATAL, "Listen fail!! errno is: %d, errmessage is: %s", errno, strerror(errno));
            exit(LISTEN_ERR);
        }
        lg(INFO, "Listen sucess!!");
    }
    void Start() // 服务器运行
    {
        //守护进程
        Deamon();
        // 获取线程池实例并让线程池运行起来
        threadpool<Task>::GetInstacne()->start();

        // 1.获取连接
        struct sockaddr_in client; // 获取对方信息的结构体
        socklen_t len = sizeof(client);
        while (true)
        {
            int sock_fd = accept(listen_fd, (sockaddr *)&client, &len); // 返回提供服务的sock_fd
            if (sock_fd < 0)
            {
                // 获取连接失败，继续获取
                lg(WARNING, "Accept fail!!! ");
                continue;
            }
            // 获取成功
            lg(INFO, "Accept sucess!! sock_fd is: %d", sock_fd);

            // 顺便获取对方信息
            uint16_t clientport = ntohs(client.sin_port); // 网络转主机字节序
            char buffer[SIZE];
            inet_ntop(AF_INET, &client.sin_addr, buffer, sizeof(buffer)); // 网络地址转字符串
            std::string clientip = buffer;

            // 1.读
            //    char buffer[SIZE];
            //   ssize_t n= read(sock_fd,buffer,sizeof(buffer));
            //   if(n>0)
            //   {
            //     buffer[n]='\0';
            //     std::cout<<buffer<<std::endl;
            //   }
            //   else if(n<0)
            //   {
            //     lg(WARNING,"Read fail!!");
            //   }
            //   else{
            //     lg(WARNING,"Client close!!");
            //   }
            //   //2.写
            //   std::string echo_message="Server get a massage@";
            //   echo_message+=buffer;
            //  ssize_t w= write(sock_fd,echo_message.c_str(),echo_message.size());
            //  if(w<0)
            //  {
            //     lg(WARNING,"Write fail!!");
            //  }
            //  else if(w==0)
            //  {
            //     lg(WARNING,"Read close!!");
            //  }

            // 线程池
            Task t(sock_fd, clientip, clientport); // 构造任务
            threadpool<Task>::GetInstacne()->push(t);
            
        }
    }

    ~TcpServer()
    {
    }
};